﻿
namespace n_MusicForm
{
using System;
using System.Drawing;
using System.Windows.Forms;

using c_MIDI;
using n_MusicFunction;
using n_MusicPanel;
using n_MusicSystemData;
using n_PianoPanel;
using n_Node;
using n_YSelectForm;
using n_TNodeSet;

/// <summary>
/// Description of WorkForm.
/// </summary>
public partial class MusicForm : Form
{
	PianoPanel PianoPad;
	
	YSelectForm YSelectBox;
	public int Volume;
	MusicPanel myMusicPanel;
	
	TNodeSet TNodeSet0;
	TNodeSet TNodeSet1;
	
	public static int SelectIndex;
	
	bool isOK;
	
	public bool MainRun;
	bool UserChange;
	
	string Filter = "linkboy音乐文件(*.iny)|*.iny|其他扩展名音乐文件|*.*";
	
	int LastWidth;
	int LastHeight;
	
	int CurrentTime;
	int[] TimerList = new int[] { 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128 };
	int CurrentTimeIndex;
	const int CurrentTimeIndexLength = 14;
	
	//主窗口
	public MusicForm( string FileName, bool vMainRun )
	{
		//
		// The InitializeComponent() call is required for Windows Forms designer support.
		//
		InitializeComponent();
		
		n_Main.Program.f = this;
		
		MainRun = vMainRun;
		
		if( !MainRun ) {
			n_SG.SG.MString.AddNewFont( "宋体", true );
		}
		
		button确定.Visible = false;
		
		SystemData.Init();
		SystemData.Load();
		
		PianoPad = new PianoPanel();
		PianoPad.Volume = SystemData.MainVolume;
		PianoPad.Location = new Point( 0, 0 );
		PianoPad.MyKeyPress += new PianoPanel.MyKeyPressEventHandler( UserKeyDown );
		this.panel4.Controls.Add( PianoPad );
		PianoPad.Location = new Point( -trackBar2.Value, 0 );
		
		SelectIndex = 0;
		
		CurrentTime = 32;
		CurrentTimeIndex = 9;
		//this.labelTime.Text = CurrentTime.ToString();
		RefreshTime();
		
		isOK = false;
		
		UserChange = true;
		
		YSelectBox = new YSelectForm();
		YSelectBox.ChannelNumber = 1;
		
		this.trackBar1.Value = SystemData.MainVolume;
		Volume = SystemData.MainVolume;
		
		
		TNodeSet0 = new TNodeSet( 0 );
		TNodeSet1 = new TNodeSet( 1 );
		TNodeSet.d_SelChanged = SelChanged;
		TNode.DebugMode = false;
		
		myMusicPanel = new MusicPanel( TNodeSet0, TNodeSet1, panelImage.Width, this.panelImage.Height );
		this.panelImage.Controls.Add( myMusicPanel );
		
		LastWidth = this.panelImage.Width;
		LastHeight = this.panelImage.Height;
		
		MessageChanged( null, null );
		
		if( FileName != null ) {
			OpenFile( FileName );
		}
		else {
			TNodeSet0.Clear();
			TNodeSet1.Clear();
		}
		myMusicPanel.LostFocus += new EventHandler( myLostFocus );
	}
	
	//显示
	public string Run( string m )
	{
		if( !MainRun ) {
			button确定.Visible = true;
		}
		
		//MessageChanged( null, null );
		
		//this.labelTime.Text = CurrentTime.ToString();
		RefreshTime();
		if( m != null && m != "" ) {
			if( !m.StartsWith( "V" ) ) {
				MessageBox.Show( "检测到此音乐数据的格式已经过时(由旧版音乐编辑器所生成), 现在新版音乐编辑器将自动升级这个音乐数据. \n" +
				                 "为了能播放新版音乐数据, 请确保您的程序中使用的音乐播放器也是最新版(如果不是最新版的话, 软件应该会已经显示一个提示框, 请按照那个提示框进行操作). \n" +
				                 "若不想升级数据, 直接关闭音乐编辑器窗口和linkboy软件, 并使用以前的旧版linkboy软件重新打开这个文件(强烈建议升级)." );
				m = n_VersionConvert.VersionConvert.Get( m );
				
				SetList( m, true );
			}
			else {
				SetList( m, false );
			}
		}
		else {
			TNodeSet0.Clear();
			TNodeSet1.Clear();
		}
		RefreshMessage();
		
		this.Show();
		this.Activate();
		myMusicPanel.Focus();
		
		while( this.Visible ) {
			System.Windows.Forms.Application.DoEvents();
		}
		if( timerPlay.Enabled ) {
			ButtonStopClick( null, null );
		}
		if( isOK ) {
			return Save();
		}
		return null;
	}
	
	//关闭
	public void Quit()
	{
		Music.Close();
		if( SystemData.isChanged ) {
			SystemData.Save();
		}
	}
	
	//没有效果
	void MusicFormLoad(object sender, EventArgs e)
	{
		myMusicPanel.Focus();
	}
	
	//窗体关闭事件
	void SetIDEFormFormClosing(object sender, FormClosingEventArgs e)
	{
		if( MainRun ) {
			DialogResult dr = MessageBox.Show( "需要保存音乐文件吗?", "保存提示", MessageBoxButtons.YesNoCancel );
			if( dr == DialogResult.Yes ) {
				e.Cancel = true;
				ButtonSaveClick( null, null );
				return;
			}
			else if( dr == DialogResult.Cancel ) {
				e.Cancel = true;
				return;
			}
			else {
				//...
			}
			Quit();
		}
		else {
			
			DialogResult dr = MessageBox.Show( "需要更新当前音乐到音乐元素中吗?", "更新提示", MessageBoxButtons.YesNo );
			if( dr == DialogResult.Yes ) {
				isOK = true;
			}
			else {
				isOK = false;
			}
			
			this.Visible = false;
			e.Cancel = true;
		}
	}
	
	void myLostFocus(object sender, EventArgs e)
	{
		//强行获取焦点导致文本框无法修改
		//myMusicPanel.Focus();
	}
	
	void PanelImageSizeChanged(object sender, EventArgs e)
	{
		if( myMusicPanel != null ) {
			//计算上一次起点...
			PointF p = myMusicPanel.GetWorldPoint( 0, 0, LastWidth, LastHeight );
		
			LastWidth = this.panelImage.Width;
			LastHeight = this.panelImage.Height;
		
			PointF p1 = myMusicPanel.GetWorldPoint( 0, 0 );
			myMusicPanel.CamMidX += p.X - p1.X;
			myMusicPanel.CamMidY += p.Y - p1.Y;
		}
	}
	
	void Button确定Click(object sender, EventArgs e)
	{
		isOK = true;
		this.Visible = false;
	}
	
	void Button开始记录Click(object sender, EventArgs e)
	{
		TNodeSet0.Clear();
		TNodeSet1.Clear();
		myMusicPanel.Invalidate();
	}
	
	void ButtonSaveClick(object sender, EventArgs e)
	{
		//保存文件对话框
		SaveFileDialog SaveFileDlg = new SaveFileDialog();
		SaveFileDlg.Filter = Filter;
		SaveFileDlg.Title = "音乐文件另存为...";
		SaveFileDlg.FileName = myMusicPanel.Title + ".iny";
		
		DialogResult dlgResult = SaveFileDlg.ShowDialog();
		if(dlgResult == DialogResult.OK) {
			string FilePath = SaveFileDlg.FileName;
			if( !FilePath.ToLower().EndsWith( ".iny" ) ) {
				FilePath += ".iny";
			}
			n_OS.VIO.SaveTextFile( FilePath, Save() );
		}
	}
	
	void ButtonOpenClick(object sender, EventArgs e)
	{
		//打开文件对话框
		OpenFileDialog OpenFileDlg = new OpenFileDialog();
		OpenFileDlg.Filter = Filter;
		OpenFileDlg.Title = "请选择linkboy音乐文件";
		OpenFileDlg.InitialDirectory = n_OS.OS.SystemRoot + @"user\music";
		
		DialogResult dlgResult = OpenFileDlg.ShowDialog();
		if(dlgResult == DialogResult.OK) {
			
			if( timerPlay.Enabled ) {
				ButtonStopClick( null, null );
			}
			OpenFile( OpenFileDlg.FileName );
			
			myMusicPanel.Invalidate();
		}
	}
	
	void OpenFile( string FileName )
	{
		string m = n_OS.VIO.OpenTextFile( FileName );
		SetList( m, false );
		RefreshMessage();
	}
	
	string Save()
	{
		string r = "V1 " + myMusicPanel.Title + ";" + myMusicPanel.Mes + "\n";
		r += TNodeSet0.Save() + "\n";
		r += TNodeSet1.Save();
		return r;
	}
	
	void SetList( string s, bool old )
	{
		string[] spn = s.Split( '\n' );
		
		myMusicPanel.Version = n_VersionConvert.VersionConvert.GetVersion( spn[0] );
		myMusicPanel.Title = n_VersionConvert.VersionConvert.GetTitle( spn[0] );;
		myMusicPanel.Mes = n_VersionConvert.VersionConvert.GetMes( spn[0] );;
		
		TNodeSet0.Open( spn[1], old );
		//TNodeSet0.RefreshSize();
		if( spn.Length == 3 ) {
			TNodeSet1.Open( spn[2], old );
			//TNodeSet1.RefreshSize();
		}
		RefreshSize();
	}
	
	//刷新尺寸
	void RefreshSize()
	{
		TNodeSet0.StartRefreshSize();
		TNodeSet1.StartRefreshSize();
		
		bool ok0 = false;
		bool ok1 = false;
		do {
			do {
				ok0 = TNodeSet0.RefreshSizeOk();
			}
			while( !ok0 && !TNodeSet0.isPerNoteEnd );
			
			do {
				ok1 = TNodeSet1.RefreshSizeOk();
			}
			while( !ok1 && !TNodeSet1.isPerNoteEnd );
			
			if( TNodeSet0.CX != 20 && TNodeSet1.CX != 20 ) {
				if( TNodeSet0.CX > TNodeSet1.CX && !ok0 ) {
					TNodeSet1.CX = TNodeSet0.CX;
				}
				else if( TNodeSet1.CX > TNodeSet0.CX && !ok1 ) {
					TNodeSet0.CX = TNodeSet1.CX;
				}
				else {
					//...
				}
			}
		}
		while( !ok0 || !ok1 );
	}
	
	//===================================================================
	//键盘
	
	void TrackBar2Scroll(object sender, EventArgs e)
	{
		PianoPad.Location = new Point( -trackBar2.Value, PianoPad.Location.Y );
	}
	
	void CheckBox滑动模式CheckedChanged(object sender, EventArgs e)
	{
		//PianoPad.isMoveMode = this.checkBox滑动模式.Checked;
	}
	
	//按键事件
	void UserKeyDown( int ToneIndex )
	{
		if( TNodeSet.SelectedTNode == null ) {
			if( radioButtonC1.Checked ) {
				TNodeSet0.AddEnd( ToneIndex, CurrentTime, checkBoxLianYin.Checked );
				//TNodeSet0.RefreshSize();
			}
			else {
				TNodeSet1.AddEnd( ToneIndex, CurrentTime, checkBoxLianYin.Checked );
				//TNodeSet1.RefreshSize();
			}
		}
		else {
			//TNodeSet.SelectedTNode.Tone = ToneIndex;
			
			TNodeSet.SelectedTNode.owner.Add( ToneIndex, CurrentTime );
			//TNodeSet.SelectedTNode.owner.RefreshSize();
		}
		RefreshSize();
		
		myMusicPanel.Invalidate();
		
	}
	
	void Button休止Click(object sender, EventArgs e)
	{
		UserKeyDown( 0 );
	}
	
	//曲谱信息改变事件
	void MessageChanged(object sender, EventArgs e)
	{
		if( !UserChange ) {
			return;
		}
		string[] ss = this.textBox歌曲名称.Text.Replace( "\r\n", "\n" ).Split( '\n' );
		if( ss.Length > 2 ) {
			MessageBox.Show( "<" + ss[0] + "+" + ss[1] + "+" + ss[2] + "> " + "歌曲名称文本框, 第一行为名称, 第二行可输入编辑者的一些信息, 第三行和之后行的文本信息将忽略无效!" );
		}
		myMusicPanel.Title = ss[0];
		if( ss.Length > 1 ) {
			myMusicPanel.Mes = ss[1];
		}
		else {
			myMusicPanel.Mes = "";
		}
		
		TNodeSet0.Volume = this.trackBarMainVolume.Value;
		TNodeSet1.Volume = this.trackBarSecondVolume.Value;
		
		try { TNode.TimeTick = int.Parse( this.textBox时值单位.Text ); } catch {}
		try { TNode.DoEqual = int.Parse( this.textBox移调偏移.Text ); } catch {}
		
		int PiN = TNode.PiN;
		int Fen = TNode.Fen;
		try { PiN = int.Parse( this.textBox拍数.Text ); } catch {}
		try { Fen = int.Parse( this.textBox音符.Text ); } catch {}
		if( PiN != TNode.PiN || Fen != TNode.Fen ) {
			TNode.PiN = PiN;
			TNode.Fen = Fen;
			//TNodeSet0.RefreshSize();
			//TNodeSet1.RefreshSize();
			RefreshSize();
		}
		myMusicPanel.Invalidate();
	}
	
	//更新曲谱信息
	void RefreshMessage()
	{
		UserChange = false;
		
		this.textBox歌曲名称.Text = myMusicPanel.Title + "\r\n" + myMusicPanel.Mes;
		this.trackBarMainVolume.Value = TNodeSet0.Volume;
		this.trackBarSecondVolume.Value = TNodeSet1.Volume;
		
		this.textBox时值单位.Text = TNode.TimeTick.ToString();
		this.textBox移调偏移.Text = TNode.DoEqual.ToString();
		
		this.textBox拍数.Text = TNode.PiN.ToString();
		this.textBox音符.Text = TNode.Fen.ToString();
		
		UserChange = true;
	}
	
	//===================================================================
	
	//调整时值
	public void UpDown( int delta )
	{
		/*
		bool HaseDot = checkBoxDot.Checked;
		if( HaseDot ) {
			CurrentTime = CurrentTime / 3 * 2;
		}
		*/
		
		/*
		if( delta > 0 ) {
			
			if( CurrentTime == 64 ) {
				CurrentTime = 96;
			}
			else if( CurrentTime == 96 ) {
				CurrentTime = 128;
			}
			else {
				CurrentTime *= 2;
				if( CurrentTime > 128 ) {
					CurrentTime = 2;
				}
			}
		}
		else {
			if( CurrentTime == 128 ) {
				CurrentTime = 96;
			}
			else if( CurrentTime == 96 ) {
				CurrentTime = 64;
			}
			else {
				CurrentTime /= 2;
				if( CurrentTime < 2 ) {
					CurrentTime = 128;
				}
			}
		}
		*/
		
		if( delta > 0 ) {
			
			++CurrentTimeIndex;
			if( CurrentTimeIndex == CurrentTimeIndexLength ) {
				CurrentTimeIndex = 0;
			}
		}
		else {
			--CurrentTimeIndex;
			if( CurrentTimeIndex < 0 ) {
				CurrentTimeIndex = CurrentTimeIndexLength - 1;
			}
		}
		CurrentTime = TimerList[CurrentTimeIndex];
		
		/*
		if( HaseDot ) {
			CurrentTime = CurrentTime / 2 * 3;
		}
		*/
		
		//this.labelTime.Text = CurrentTime.ToString();
		RefreshTime();
		if( TNodeSet.SelectedTNode != null ) {
			TNodeSet.SelectedTNode.Time = CurrentTime;
			//TNodeSet.SelectedTNode.owner.RefreshSize();
			
			RefreshSize();
			
			myMusicPanel.Invalidate();
		}
	}
	
	void ButtonDownClick(object sender, EventArgs e)
	{
		UpDown( -1 );
	}
	
	void ButtonUpClick(object sender, EventArgs e)
	{
		UpDown( 1 );
	}
	
	void CheckBoxLianYinCheckedChanged(object sender, EventArgs e)
	{
		if( TNodeSet.SelectedTNode != null ) {
			TNodeSet.SelectedTNode.LianYin = this.checkBoxLianYin.Checked;
			myMusicPanel.Invalidate();
		}
	}
	
	void Button删除Click(object sender, EventArgs e)
	{
		TNodeSet.SelectedTNode.owner.Delete();
		RefreshSize();
		myMusicPanel.Invalidate();
	}
	
	void SelChanged()
	{
		if( TNodeSet.SelectedTNode != null ) {
			CurrentTime = TNodeSet.SelectedTNode.Time;
			this.labelTime.Text = CurrentTime.ToString();
			UserChange = false;
			//checkBoxDot.Checked = CurrentTime%3==0;
			UserChange = true;
			
			if( TNodeSet.SelectedTNode.owner.Channel == 0 ) {
				radioButtonC1.Checked = true;
			}
			else {
				radioButtonC2.Checked = true;
			}
			this.checkBoxLianYin.Checked = TNodeSet.SelectedTNode.LianYin;
			
			button删除.Visible = true;
		}
		else {
			button删除.Visible = false;
		}
	}
	
	void RefreshTime()
	{
		this.labelTime.Text = CurrentTime.ToString();
		/*
		if( CurrentTime == 1 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 2 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 3 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 4 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 6 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 8 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 12 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 16 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 24 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 32 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 48 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 64 ) {
			this.labelTime.Text = "";
		}
		else if( CurrentTime == 96 ) {
			this.labelTime.Text = "";
		}
		else {
			this.labelTime.Text = "";
		}
		*/
	}
	
	//===================================================================
	
	void CheckBox显示网格CheckedChanged(object sender, EventArgs e)
	{
		TNode.DebugMode = this.checkBox显示网格.Checked;
		myMusicPanel.ShowNetGrid = this.checkBox显示网格.Checked;
		myMusicPanel.Invalidate();
	}
	
	void TrackBarJNumberScroll(object sender, EventArgs e)
	{
		TNodeSet0.NumberPerLine = this.trackBarJNumber.Value;
		//TNodeSet0.RefreshSize();
		TNodeSet1.NumberPerLine = this.trackBarJNumber.Value;
		//TNodeSet1.RefreshSize();
		
		RefreshSize();
		
		myMusicPanel.Invalidate();
		
		this.labelJNumber.Text = "每一行的小节数目：(" + this.trackBarJNumber.Value + ")";
	}
	
	//==============================================================================
	bool Play0;
	TNode LastTone0;
	int Tick0;
	int Time0;
	
	bool Play1;
	TNode LastTone1;
	int Tick1;
	int Time1;
	
	void PlayInit()
	{
		Play0 = false;
		LastTone0 = null;
		Tick0 = 0;
		Time0 = 0;
		
		Play1 = false;
		LastTone1 = null;
		Tick1 = 0;
		Time1 = 0;
	}
	
	//音量调节
	void TrackBar1Scroll(object sender, EventArgs e)
	{
		Volume = ( (TrackBar)sender ).Value;
		PianoPad.Volume = Volume;
		SystemData.MainVolume = Volume;
		SystemData.isChanged = true;
	}
	
	void Button选择音色Click(object sender, EventArgs e)
	{
		YSelectBox.Run();
	}
	
	void Button播放Click(object sender, EventArgs e)
	{
		if( button播放.Text == "播放" ) {
			button播放.Text = "暂停";
			timerPlay.Enabled = true;
			Play0 = true;
			Time0 = 1;
			Tick0 = 0;
			Play1 = true;
			Time1 = 1;
			Tick1 = 0;
		}
		else if( button播放.Text == "暂停" ) {
			button播放.Text = "继续";
			timerPlay.Enabled = false;
		}
		else if( button播放.Text == "继续" ) {
			button播放.Text = "暂停";
			timerPlay.Enabled = true;
		}
		else {
			//...
		}
	}
	
	void ButtonStopClick(object sender, EventArgs e)
	{
		timerPlay.Enabled = false;
		StopPlay0();
		StopPlay1();
		button播放.Text = "播放";
	}
	
	void TimerPlayTick(object sender, EventArgs e)
	{
		int sc = 4;
		
		this.timerPlay.Interval = TNode.TimeTick * sc;
		
		if( !Play0 && !Play1 ) {
			timerPlay.Enabled = false;
			button播放.Text = "播放";
			return;
		}
		if( Play0 ) {
			Tick0++;
			if( Tick0 == Time0 ) {
				Tick0 = 0;
				//读取下一个音符
				TNodeSet0.PlayIndex++;
				if( TNodeSet0.PlayIndex == TNodeSet0.TNodeListLength ) {
					StopPlay0();
					return;
				}
				TNode ct = TNodeSet0.TNodeList[TNodeSet0.PlayIndex];
				
				//播放音符
				if( (LastTone0 == null || !LastTone0.LianYin) || ct.Tone != LastTone0.Tone ) {
					if( LastTone0 != null && LastTone0.Tone != 0 ) {
						Music.CloseSound( 0, GetRealTone( LastTone0.Tone ) );
					}
					if( ct.Tone != 0 ) {
						Music.PlaySound( 0, GetRealTone( ct.Tone ), Volume * TNodeSet0.Volume / 127 );
					}
				}
				LastTone0 = ct;
				
				//处理时间
				Time0 = ct.Time;
				Time0 /= sc;
				if( Time0 == 0 ) Time0 = 1;
			}
		}
		if( Play1 ) {
			Tick1++;
			if( Tick1 == Time1 ) {
				Tick1 = 0;
				//读取下一个音符
				TNodeSet1.PlayIndex++;
				if( TNodeSet1.PlayIndex == TNodeSet1.TNodeListLength ) {
					StopPlay1();
					return;
				}
				TNode ct = TNodeSet1.TNodeList[TNodeSet1.PlayIndex];
				
				//播放音符
				if( (LastTone1 == null || !LastTone1.LianYin) || ct.Tone != LastTone1.Tone ) {
					if( LastTone1 != null && LastTone1.Tone != 0 ) {
						Music.CloseSound( 1, GetRealTone( LastTone1.Tone ) );
					}
					if( ct.Tone != 0 ) {
						Music.PlaySound( 1, GetRealTone( ct.Tone ), Volume * TNodeSet1.Volume / 127 );
					}
				}
				LastTone1 = ct;
				
				//处理时间
				Time1 = ct.Time;
				Time1 /= sc;
				if( Time1 == 0 ) Time1 = 1;
			}
		}
		myMusicPanel.Invalidate();
	}
	
	//结束播放
	void StopPlay0()
	{
		if( LastTone0 != null ) {
			Music.CloseSound( 0, GetRealTone( LastTone0.Tone ) );
		}
		LastTone0 = null;
		Play0 = false;
		TNodeSet0.PlayIndex = -1;
		myMusicPanel.Invalidate();
	}
	
	//结束播放
	void StopPlay1()
	{
		if( LastTone1 != null ) {
			Music.CloseSound( 1, GetRealTone( LastTone1.Tone ) );
		}
		LastTone1 = null;
		Play1 = false;
		TNodeSet1.PlayIndex = -1;
		myMusicPanel.Invalidate();
	}
	
	int GetRealTone( int t )
	{
		return t + TNode.DoEqual - 60;
	}
}
}





